package XML;

import java.io.File;
import java.io.IOException;
import java.util.Vector;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;


public class XMLParser {
	
	static Document document;

	public static Vector<FragmentXML> parser(String path){
		
		Vector<FragmentXML> res=new Vector<FragmentXML>();
		
		DocumentBuilderFactory factory =DocumentBuilderFactory.newInstance();

		try {
			DocumentBuilder builder = factory.newDocumentBuilder();
			document = builder.parse( new File(path));
			
			
			//get the root element
			Element docEle = document.getDocumentElement();

			//get a nodelist of  elements
			NodeList nl = docEle.getElementsByTagName("Fragment");
			
			if(nl != null && nl.getLength() > 0) {
				for(int i = 0 ; i < nl.getLength();i++) {

					//get the FragmentXML element
					Element el = (Element)nl.item(i);

					//get the FragmentXML object
					FragmentXML e = getFragment(el);

					//add it to list
					res.add(e);
				}
			}
			
										
		  } catch (SAXParseException spe) {
		    // Error generated by the parser
		    System.out.println("\n** Parsing error"
		      + ", line " + spe.getLineNumber()
		      + ", uri " + spe.getSystemId());
		    System.out.println("   " + spe.getMessage() );
		  
		    // Use the contained exception, if any
		    Exception  x = spe;
		    if (spe.getException() != null)
		      x = spe.getException();
		    x.printStackTrace();

		  } catch (SAXException sxe) {
		    // Error generated during parsing
		    Exception  x = sxe;
		    if (sxe.getException() != null)
		      x = sxe.getException();
		    x.printStackTrace();

		  } catch (ParserConfigurationException pce) {
		    // Parser with specified options can't be built
		    pce.printStackTrace();

		  } catch (IOException ioe) {
		    // I/O error
		    ioe.printStackTrace();
		  }
		  
		  
		return res;

	}
	
	/**
	 * I take a Fragment element and read the values in, create
	 * a Fragment object and return it
	 */
	private static FragmentXML getFragment(Element fragEl) {

		String name = getTextValue(fragEl,"Name");
		Vector<String> input = getListTextValue(fragEl,"Input");
		Vector<String> output = getListTextValue(fragEl,"Output");
		Integer preference = getIntValue(fragEl, "Pref");
		

		//Create a new Employee with the value read from the xml nodes
		
		FragmentXML f;
		if(!(preference==null))
			 f= new FragmentXML(name,input,output,preference.intValue());
		else
			f= new FragmentXML(name,input,output,0);
		
		return f;
	}


	/**
	 * I take a xml element and the tag name, look for the tag and get
	 * the text content
	 */
	private static String getTextValue(Element ele, String tagName) {
		String textVal = null;
		NodeList nl = ele.getElementsByTagName(tagName);
		if(nl != null && nl.getLength() > 0) {
			Element el = (Element)nl.item(0);
			textVal = el.getFirstChild().getNodeValue();
		}

		return textVal;
	}
	
	/**
	 * I take a xml element and the tag name, look for the tag and get
	 * the vector of text content
	 */
	private static Vector<String> getListTextValue(Element ele, String tagName) {
		Vector<String> textVal = new Vector<String>();
		NodeList nl = ele.getElementsByTagName(tagName);
		if(nl != null && nl.getLength() > 0) {
			for(int i=0;i<nl.getLength();i++){
					textVal.add( ((Element)nl.item(i)).getFirstChild().getNodeValue());
			}
		return textVal;
		}

		return textVal;
	}
	
	/**
	 * Calls getTextValue and returns a int value
	 */
	private static Integer getIntValue(Element ele, String tagName) {
		//in production application you would catch the exception
		
		if (getTextValue(ele,tagName) == null) return null;
		
		return Integer.parseInt(getTextValue(ele,tagName));
	}




	
}
